package com.glsc.ngateway.platform.utils;

import com.glsc.ngateway.common.api.common.enums.DictConstant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author zhouzp
 * @date 2020/4/29
 * 根据上下文获取spring容器对象工具类
 */
@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtil.applicationContext = applicationContext;
    }

    /**
     * @Description: 根据名字获取spring容器管理的对象
     */
    public static <T> T getBean(String beanName) {
        if(applicationContext.containsBean(beanName)){
            return (T) applicationContext.getBean(beanName);
        }else{
            return null;
        }
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> baseType){
        return applicationContext.getBeansOfType(baseType);
    }

    /**
     * @Description: 获取当前request
     * @throws IllegalStateException 当前线程不是web请求抛出此异常.
     */
    public static HttpServletRequest getCurrentRequest() throws IllegalStateException {
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attrs == null) {
            throw new IllegalStateException("当前线程中不存在 Request 上下文");
        }
        return attrs.getRequest();
    }


    //获取对象值非空的属性列表
    public static String[] getNullPropertyNames (Object source, Object target) {
        if(null==source){
            return null;
        }

        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] srcProps = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        Set<String> srcPropNames=new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : srcProps) {
            srcPropNames.add(pd.getName());

            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];

        java.beans.PropertyDescriptor[] targetProps = new BeanWrapperImpl(target).getPropertyDescriptors();
        Set<String> targetPropNames=new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : targetProps) {
            targetPropNames.add(pd.getName());
        }

        for(String propName:targetPropNames){
            if(!srcPropNames.contains(propName)){
                emptyNames.add(propName);//如果源对象没有此属性，也忽略
            }
        }

        return emptyNames.toArray(result);
    }

    /**
     * 拷贝源对象的属性到目的对象，忽略源对象中值为null的属性；支持src和target类型不一致
     * @param src 源对象
     * @param target 目的对象
     */
    public static void copyPropertiesIgnoreNull(Object src, Object target){
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src,target));
    }

    /**
     * 获取activeProfile
     *
     */
    public static String getActiveProfile() {
        return applicationContext.getEnvironment().getActiveProfiles()[0];
    }

    /**
     * 判断是否为测试环境
     *
     */
    public static boolean isTestingByActiveProfile() {
        String currentActiveProfile = SpringUtil.getActiveProfile();//判断生产还是测试环境

        if(DictConstant.SYSTEM_ACTIVE_PROFILE_PROD.equalsIgnoreCase(currentActiveProfile)){
            return false;
        }else{
            return true;
        }
    }
}
